package com.pmcc.core.service;

import com.pmcc.core.config.security.JwtUser;
import com.pmcc.core.entity.security.Menu;
import com.pmcc.core.entity.security.Role;
import com.pmcc.core.enums.RoleType;
import com.pmcc.core.repository.MenuRepository;
import com.pmcc.core.repository.RoleRepository;
import com.pmcc.core.vo.RoleVO;
import com.pmcc.utils.AntPage;
import com.pmcc.utils.BeanUtils;
import com.pmcc.utils.ResultBean;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class RoleService {

    @Autowired
    RoleRepository roleRepository;

    @Autowired
    MenuRepository menuRepository;

    /**
     * 根据登录人，查询其创建角色
     *
     * @param antPage
     * @param jwtUser
     * @return
     */
    public ResultBean queryByPage(AntPage antPage, JwtUser jwtUser) {
        ResultBean resultBean = new ResultBean();
        Page<Role> rolePage = roleRepository.findAll(this.getSpecification(jwtUser), antPage.getPageRequest());
        resultBean.setRows(this.getRoleVOList(rolePage.getContent()));
        resultBean.setPage(antPage.getPage());
        resultBean.setPageSize(antPage.getPageSize());
        resultBean.setResultCode(ResultBean.SUCCESS);
        return resultBean;
    }


    private Specification<Role> getSpecification(JwtUser jwtUser) {
        return (Root<Role> root, CriteriaQuery<?> query, CriteriaBuilder builder) -> {
            List<Predicate> list = new ArrayList<Predicate>();
            //创建人
            if (StringUtils.isNotEmpty(jwtUser.getId())) {
                list.add(builder.equal(root.get("createId").as(String.class), jwtUser.getId().trim()));
            }
            list.add(builder.equal(root.get("delFlag").as(String.class), "0"));
            Predicate[] p = new Predicate[list.size()];
            return builder.and(list.toArray(p));
        };
    }

    private List<RoleVO> getRoleVOList(List<Role> list) {
        List<RoleVO> voList = new ArrayList<>();
        for (Role role : list) {
            RoleVO vo = new RoleVO();
            BeanUtils.copyProperties(role, vo);
            voList.add(vo);
        }
        return voList;
    }

    public List<RoleVO> queryList() {
        List<Role> roleList = roleRepository.findAll();
        return this.getRoleVOList(roleList);
    }

    public ResultBean saveOrUpdate(Role role) {
        ResultBean resultBean = new ResultBean();
        JwtUser jwtUser = (JwtUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        if (role.getType() != RoleType.SYSTEM_ROLE) {
            Role typeRole = roleRepository.findByType(role.getType());
            if (StringUtils.isEmpty(role.getId())&&typeRole!=null) {
                resultBean.setResultDesc("该类型角色只能创建一个，不能创建多个！");
                resultBean.setResultCode(ResultBean.FAIL);
                return resultBean;
            }else {
                if (typeRole != null && !role.getId().equals(typeRole.getId())) {
                    resultBean.setResultDesc("该类型角色已存在，不能创建多个！");
                    resultBean.setResultCode(ResultBean.FAIL);
                    return resultBean;
                }
            }
        }

        Role codeRole = roleRepository.findByCode(role.getCode());
        if (StringUtils.isEmpty(role.getId())&&codeRole!=null) {
            resultBean.setResultDesc("角色编码重复，请修改后重新保存！");
            resultBean.setResultCode(ResultBean.FAIL);
            return resultBean;
        }else {
            if (codeRole != null && !role.getId().equals(codeRole.getId())) {
                resultBean.setResultDesc("角色编码重复，请修改后重新保存！");
                resultBean.setResultCode(ResultBean.FAIL);
                return resultBean;
            }
        }

        if (StringUtils.isEmpty(role.getId())) {
            role.setDelFlag("0");
            role.setState("1");
            role.setCreateId(jwtUser.getId());
            role.setCreateTime(new Date());
            roleRepository.save(role);
            resultBean.setResultDesc("新增成功！");
        } else {
            Role oldRole = roleRepository.findOne(role.getId());
            oldRole.setModifyId(jwtUser.getId());
            oldRole.setModifyName(jwtUser.getUserCName());
            oldRole.setCode(role.getCode());
            oldRole.setName(role.getName());
            oldRole.setDescription(role.getDescription());
            oldRole.setState(role.getState());
            oldRole.setType(role.getType());
            roleRepository.save(oldRole);
            resultBean.setResultDesc("修改成功！");
        }
        resultBean.setResultCode(ResultBean.SUCCESS);
        return resultBean;
    }

    public ResultBean delete(Role model) {
        ResultBean resultBean = new ResultBean();
        Role role = roleRepository.findOne(model.getId());
        roleRepository.delete(role);
        resultBean.setResultCode(ResultBean.SUCCESS);
        return resultBean;
    }

    public ResultBean saveRoleMenus(String roleId, List<String> menus) {
        ResultBean resultBean = new ResultBean();
        Role role = roleRepository.findOne(roleId);
        role.getMenuSet().clear();

        List<Menu> menuList = menus.stream().map(menuId -> menuRepository.findOne(menuId)).collect(Collectors.toList());
        for (Menu obj : menuList) {
            obj.getRoleList().add(role);
            role.getMenuSet().add(obj);
        }
        roleRepository.save(role);
        resultBean.setResultDesc("配置成功！");
        resultBean.setResultCode(ResultBean.SUCCESS);
        return resultBean;
    }

    public ResultBean queryRoleMenu(String roleId) {
        ResultBean resultBean = new ResultBean();
        Role role = roleRepository.findOne(roleId);
        List<String> list = role.getMenuSet().stream().map(Menu::getId).collect(Collectors.toList());
        resultBean.setRows(list);
        resultBean.setResultCode(ResultBean.SUCCESS);
        return resultBean;
    }
}
